import {
    _decorator,
    Component,
    Label,
    Node,
    view,
} from "cc";
import { createUINode } from "../utils";
import { ControllerManager } from "../UI/ControllerManager";
import DataManager from "../Runtime/DataManager";
import seedRandom from "../utils/seedrandom.min.js"
import { TileMapManager } from "../Tile/TileMapManager";
import { CollisionDetection } from "../Runtime/CollisionDetection";
import { GameElement } from "../UI/GameElement";
import { GAME_MODE_ENUM, SOCKET_TYPE } from "../../Enums";
import { AudioMgr } from "../Runtime/AudioMgr"
import { GamePlayer } from "../Role/GamePlayer";
import EventManager from "../Runtime/EventManager";
import { userStore } from "../service/user";
import { CommonElement } from "../UI/CommonElement";
import { sendSocket } from '../service/socket';
const { ccclass } = _decorator;
@ccclass("gameManager")
export class gameManager extends Component {
    controllerManager
    operationNode
    fractionNumber
    play_music: boolean = false
    gameNode: Node
    ping
    synchro
    ready: boolean = false
    game_over: boolean = false //游戏是否结束
    async onLoad() {
        DataManager.Instance.player = []
        const node = createUINode("gameManager")
        this.controllerManager = node.addComponent(ControllerManager)
        node.setParent(this.node)
        this.gameNode = node
        // 初始化关卡
        if (DataManager.Instance.gameMode == GAME_MODE_ENUM.ONLINE) {
            setTimeout(async () => {
                await this.controllerManager.showLoading()
            }, 100)
        }
        await this.controllerManager.loadAssortAssets(DataManager.Instance.gameMode != GAME_MODE_ENUM.ONLINE)
        if (DataManager.Instance.audioMgr == null) {
            DataManager.Instance.audioMgr = new AudioMgr()
        }
        if (!DataManager.Instance.mute) {
            DataManager.Instance.audioMgr.play(DataManager.Instance.audio.find(item => item.name == '1256_game_music'), 1)
            this.play_music = true
        }
        // 屏幕上的元素
        const gameNode = createUINode("gameNode")
        gameNode.setParent(this.node)
        const commonElement = node.addComponent(CommonElement)
        const gameElement = node.addComponent(GameElement)
        gameElement.init({ controllerManager: this.controllerManager, play_music: this.play_music, commonElement })
        DataManager.Instance.gameElement = gameElement
        this.initMap()
        EventManager.Instance.on('restartGame', this.initMap, this);
        EventManager.Instance.on("msg", this.websocketMessage, this)
        userStore().share()
        if (DataManager.Instance.gameMode == GAME_MODE_ENUM.ONLINE) {
            // 网络延时
            this.ping = setInterval(() => {
                let start_time = new Date().getTime()
                DataManager.Instance.start_time = start_time
                sendSocket(SOCKET_TYPE.PING, {
                    start_time,
                })
            }, 1000)
        }
    }
    initMap() {
        clearInterval(this.synchro)
        // 地图信息
        const tileMapManager = this.gameNode.addComponent(TileMapManager)
        tileMapManager.init()
        // 碰撞检测
        const collisionDetection = this.gameNode.addComponent(CollisionDetection)
        collisionDetection.init({ controllerManager: this.controllerManager })

        this.node.getChildByName("gameNode").setPosition(0, 0)
        this.node.getChildByName("Camera").setPosition(0, 0)
        if (DataManager.Instance.gameMode == GAME_MODE_ENUM.ONLINE) {
            let list = []
            DataManager.Instance.async_scence.forEach(item => {
                list.push(this.getScenceList({ socket_number: 0, item }))
            })
            setTimeout(() => {
                sendSocket(SOCKET_TYPE.INIT, list)
            }, 10)
            DataManager.Instance.socket_number = 0
            // 每150毫秒,更新当前所有的角色到服务端,服务端来判断保留双方的哪个位置
            this.synchro = setInterval(() => {
                if (!DataManager.Instance.game_ready) return
                if (DataManager.Instance.ping_time >= 460) return //代表至少400毫秒没有收到消息,直接取对方屏幕的信息
                DataManager.Instance.socket_number = DataManager.Instance.socket_number + 1
                let list = []
                DataManager.Instance.async_scence.forEach(item => {
                    list.push(this.getScenceList({ socket_number: DataManager.Instance.socket_number, item }))
                })
                sendSocket(SOCKET_TYPE.ASYNC, list)
            }, 150)
        }
    }
    // 处理给服务端发送的数据列表
    getScenceList({ socket_number, item }) {
        let { node, type } = item
        if (item.type == 'role') {
            return { socket_number, node, type, ...item.player.getSendData() }
        } else if (item.type == 'fraction') {
            return { socket_number, node, type, fraction: DataManager.Instance.fraction }
        } else if (item.type == 'property') {
            if (item.node.includes("placeholder")) {
                return { socket_number, node, type, ...item.player }
            } else {
                return { socket_number, node, type, ...item.player.getSendData() }
            }
        } else if (item.type == 'enemy') {
            return { socket_number, node, type, ...item.player.getSendData() }
        }
    }
    async websocketMessage(data) {
        if (data.roomId != DataManager.Instance.room.id) return
        if (data.type == SOCKET_TYPE.OK) {
            DataManager.Instance.game_ready = true
            DataManager.Instance.seed_random = seedRandom(data.content)
            setTimeout(async () => {
                await this.controllerManager.hideLoading()
            }, 10)
        }
        if (data.type == SOCKET_TYPE.OFFLINE || data.type == SOCKET_TYPE.ONLINE) {
            if (DataManager.Instance.otherLine == data.content) return
            DataManager.Instance.otherLine = data.content
            console.log(`对方已${data.content?'在':'离'}线`)
        }
        if (data.type == SOCKET_TYPE.SUCCESS) {
            if (!this.game_over) {
                if (!DataManager.Instance.levelInfo.nextLevel) {
                    DataManager.Instance.gameElement.createClearance()
                } else {
                    DataManager.Instance.gameElement.createAchieve()
                }
                this.game_over = true
                clearInterval(this.synchro)
            }
            return
        }
        if (data.type == SOCKET_TYPE.FAIL) {
            if (!this.game_over) {
                DataManager.Instance.gameElement.createFail()
                this.game_over = true
                clearInterval(this.synchro)
            }
            return
        }
        if (data.type == SOCKET_TYPE.ASYNC) {
            let list = data.content
            list.forEach(item => {
                DataManager.Instance.socket_number = item.socket_number
                if (item.type == 'role') {
                    let player = DataManager.Instance.async_scence.find(item1 => item1.node == item.node).player
                    player.setSendData(item)
                } else if (item.type == 'fraction') {
                    let label = DataManager.Instance.async_scence.find(item1 => item1.node == item.node).player
                    label.getComponent(Label).string = item.fraction
                    DataManager.Instance.fraction = item.fraction
                } else if (item.type == 'property') {
                    // 占位道具
                    if (item.node.includes("placeholder")) {
                        let parent = this.node.getChildByName('gameManager').getComponent(TileMapManager).node.getChildByName('mapInfo')
                        if (parent.getChildByName(item.name)) {
                            return
                        }
                        const placeholder_node = createUINode(item.name)
                        placeholder_node.setParent(parent)
                        placeholder_node.setSiblingIndex(item.index)
                        DataManager.Instance.async_scence.push({
                            type: 'property', node: placeholder_node.name, player: {
                                index: item.index,
                                parent: item.parent,
                                name: item.name
                            }
                        })
                    } else {
                        // 其他道具
                        let player = DataManager.Instance.async_scence.find(item1 => item1.node == item.node).player
                        player.setSendData(item)
                    }
                } else if (item.type == 'enemy') {
                    let player = DataManager.Instance.async_scence.find(item1 => item1.node == item.node).player
                    player.setSendData(item)
                } else if (item.type == 'seedRandom') {
                    DataManager.Instance.seed_random = seedRandom(item.content)
                }
            })
        }
    }
    onDestroy() {
        DataManager.Instance.otherLine=true
        clearInterval(this.ping)
        clearInterval(this.synchro)
        this.play_music = false
        DataManager.Instance.audioMgr.stop()
        EventManager.Instance.off('restartGame', this.initMap);
        EventManager.Instance.off("msg", this.websocketMessage)
    }
    update() {
        if (DataManager.Instance.player.length == 1) {
            let playNode = DataManager.Instance.player[0].node
            if (!playNode) return
            this.cameraFollow(DataManager.Instance.player[0].node.getPosition())
        } else if (DataManager.Instance.player.length == 2) {
            this.anyCameraFollow()
        }
    }
    spliceDisableStatus(player, status) {
        let index = player.disable_status.findIndex(item => item == status)
        if (index != -1) {
            player.disable_status.splice(index, 1)
        }
    }
    pushDisableStatus(player, status) {
        let index = player.disable_status.findIndex(item => item == status)
        if (index == -1) {
            player.disable_status.push(status)
        }
    }
    // 多个摄像机跟随
    anyCameraFollow() {
        let green = DataManager.Instance.player[0].node
        let blue = DataManager.Instance.player[1].node
        let green_player = green.getComponent(GamePlayer)
        let blue_player = blue.getComponent(GamePlayer)
        let { height, width, position } = DataManager.Instance
        let { x: green_x, y: green_y } = green.getPosition()
        let { x: blue_x, y: blue_y } = blue.getPosition()
        let center_x = (green_x + blue_x) / 2 + width / 2
        let center_y = (green_y + blue_y) / 2 - height / 2
        // 判断是否能左右移动
        if (view.getVisibleSize().width - (blue_x - green_x) - width < 300) {
            // console.log("蓝不能往右走了")
            // console.log("绿不能往左走了")
            this.pushDisableStatus(blue_player, "right")
            this.pushDisableStatus(green_player, "left")
        } else if (view.getVisibleSize().width - (green_x - blue_x) - width < 300) {
            // console.log("绿不能往右走了")
            // console.log("蓝不能往左走了")
            this.pushDisableStatus(blue_player, "left")
            this.pushDisableStatus(green_player, "right")
        } else {
            this.spliceDisableStatus(blue_player, "left")
            this.spliceDisableStatus(blue_player, "right")
            this.spliceDisableStatus(green_player, "left")
            this.spliceDisableStatus(green_player, "right")
        }

        let max_y = view.getVisibleSize().height - height - (height - position) - 4
        // 判断是否能上下移动
        let tob_formula = Math.abs(blue_y) - Math.abs(green_y)
        if (tob_formula >= max_y - 5) {
            // console.log("蓝不能往下移动了")
            // console.log("绿不能往上移动了")
            this.pushDisableStatus(blue_player, "bottom")
            this.pushDisableStatus(green_player, "top")
        } else if (tob_formula <= -max_y + 5) {
            // console.log("蓝不能往上移动了")
            // console.log("绿不能往下移动了")
            this.pushDisableStatus(blue_player, "top")
            this.pushDisableStatus(green_player, "bottom")
        } else {
            this.spliceDisableStatus(blue_player, "top")
            this.spliceDisableStatus(blue_player, "bottom")
            this.spliceDisableStatus(green_player, "top")
            this.spliceDisableStatus(green_player, "bottom")
        }
        this.cameraFollow({
            x: center_x,
            y: center_y
        })
    }
    // 摄像机跟随
    cameraFollow(pos) {
        // 角色一直在中间,下移过了中间的点,摄像机开始移动,到最低点后不处理
        let centerY = -view.getVisibleSize().height / 2
        let centerX = -view.getVisibleSize().width / 2
        let { cameraBoundary, height, width } = DataManager.Instance
        let maxBottom = -(Math.abs(cameraBoundary.y) - view.getVisibleSize().height + height)
        let maxRight = (Math.abs(cameraBoundary.x) - view.getVisibleSize().width + width)
        let positionX = 0
        let positionY = 0
        if (Math.abs(cameraBoundary.x) > view.getVisibleSize().width) {
            if (Math.abs(pos.x) > Math.abs(centerX)) {
                positionX = Math.abs(centerX) - Math.abs(pos.x)
                if (Math.abs(positionX) > Math.abs(maxRight)) {
                    positionX = -maxRight
                } else {
                    //  console.log("不在中心点")
                }
                this.node.getChildByName("gameNode").setPosition(-positionX, positionY)
                this.node.getChildByName("Camera").setPosition(-positionX, positionY)
                //  console.log("不在中心点")
            } else {
                // console.log("中心点")
            }
        }
        if (Math.abs(cameraBoundary.y) > view.getVisibleSize().height) {
            if (Math.abs(pos.y) > Math.abs(centerY)) {
                positionY = Math.abs(centerY) - Math.abs(pos.y)
                if (Math.abs(positionY) > Math.abs(maxBottom)) {
                    positionY = maxBottom
                } else {
                    // console.log("不在中心点")
                }
                this.node.getChildByName("gameNode").setPosition(-positionX, positionY)
                this.node.getChildByName("Camera").setPosition(-positionX, positionY)
            } else {
                // console.log("在中心点内")
            }
        }
    }
    // async initLeavel() {
    //     const level = Levels[`level${DataManager.Instance.levelIndex}`];
    //     if (level) {
    //         DataManager.Instance.mapInfo = level.mapInfo;
    //     }
    // }
}

